<template>
    <a-layout-content class="content">
        <a-icon type="home" class="header-icon" />
        <div class="title-container">
            <h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-center main-title">
                <span class="bg-gradient-to-r from-ai-cyan to-ai-purple text-gradient">国粒</span>智能校园安防监控平台
            </h1>
        </div>
        <a-row :gutter="24">
        <a-row :gutter="24">
            <a-col :span="16">
                <a-card title="视频监控" class="video-card" style="animation: pulse 3s infinite ease-in-out;">
                    <div class="media-container">
                        <canvas v-if="decodeMode == 'canvas'" ref="canvasElement" class="media-element"></canvas>
                        <video v-else ref="videoElement" class="media-element"></video>
                    </div>
                </a-card>

                <a-card
                    v-show="isReplayPlayerShow"
                    title="视频监控"
                    class="video-card"
                    style="animation: pulse 3s infinite ease-in-out"
                >
                    <div class="media-container">
                        <canvas
                            v-if="decodeMode2 == 'canvas'"
                            ref="canvasElement2"
                            class="media-element"
                        ></canvas>
                        <video
                            v-else
                            ref="videoElement2"
                            class="media-element"
                        ></video>
                    </div>
                </a-card>
            </a-col>
            <a-col :span="8">
                <a-card title="事件统计" class="event-card" style="animation: pulse 3s infinite ease-in-out 0.5s;">
                    <transition-group name="count-up" tag="div">
                        <div class="event-list">
                            <div v-for="(count, eventType) in eventCounts" :key="eventType" class="stat-item">
                                <a-tag color="red"><a-icon type="info-circle" /> {{ eventType }}：{{ count }}</a-tag>
                                <!-- <span class="event-type"><a-icon type="info-circle" /> {{ eventType }}</span>
                                <span class="event-count">{{ count }}</span> -->
                            </div>
                        </div>

                    </transition-group>
                </a-card>
                <div style="height: 20px;"></div>
                <div style="animation: pulse 3s infinite ease-in-out 1s;height:690px;overflow-y: auto;scrollbar-width: none;"> 
                <a-card title="报警事件" class="event-card" >
                    <a-card v-for="(itemMessage, index) in eventMessages" :key="index" class="event-item">
                        <template #title>
                            <span>{{ itemMessage.eventName }}</span>
                        </template>
                        <div>{{ itemMessage.stringTime }}</div>
                        <div v-if="itemMessage.strangerFlag == 1">陌生人</div>
                        <div class="img-list">
                            <div class="img-box" v-for="(imageSrc, index) in itemMessage.images"
                            :key="index" >
                            <img  mode="center" :src="$imageBaseUrl + imageSrc" />
                            </div>
                        </div>
                        
                        <a-button
                            @click="onSearchRecord(itemMessage.stringTime)"
                        >
                            回放
                        </a-button>
                        <a-button @click="onPausePlayback()"> 暂停 </a-button>
                        <a-button @click="onContinuePlayback()">
                            继续
                        </a-button>
                        <a-button @click="onClosePlayback()">
                            结束回放
                        </a-button>
                    </a-card>
                </a-card>
            </div>
            </a-col>
        </a-row>
        </a-row>
    </a-layout-content>
</template>

<script setup>
import { ref, onMounted, reactive } from "vue";

onMounted(() => {
    login();
    playerPlay();
    let socket = io.connect("http://127.0.0.1:9092");
    socket.on("connect", function () {
        console.log("connected");
    });
    socket.on("event", function (eventMessage) {
        console.log("eventMessage", eventMessage);
        eventMessages.unshift(eventMessage);
        updateEventCounts(eventMessage);
    });
});
const eventMessages = reactive([]);
const eventCounts = reactive({});

let isLogin = false; //是否登录
let replayRecord = null; //录像文件
let replayPlayer = null; //录像播放器

const isReplayPlayerShow = ref(false);

function updateEventCounts(eventMessage) {
    if (!eventCounts[eventMessage.eventName]) {
        eventCounts[eventMessage.eventName] = 0;
    }
    eventCounts[eventMessage.eventName]++;
}

const canvasElement = ref();
const videoElement = ref();

const canvasElement2 = ref();
const videoElement2 = ref();

const decodeMode = ref("canvas");
const decodeMode2 = ref("canvas"); //录像播放器的解码格式

let player;

function playerPlay() {
    var options = {
        wsURL: "ws://10.168.1.100/rtspoverwebsocket",
        rtspURL:
            "rtsp://10.168.1.102/cam/realmonitor?channel=1&subtype=0&proto=Private3",
        username: "admin",
        password: "zhzy@2021",
    };
    player = new window.PlayerControl(options);
    player.on("WorkerReady", function () {
        player.connect();
    });
    player.on("DecodeStart", function (rs) {
        console.log("start decode");
        console.log(rs);
        decodeMode.value = rs.decodeMode;
    });
    player.on("PlayStart", function (rs) {
        console.log("live play");
        console.log(rs);
    });
    player.on("Error", function (rs) {
        console.log("error");
        console.log(rs);
    });
    player.on("FileOver", function (rs) {
        console.log("recorder play over");
        console.log(rs);
    });
    player.on("MSEResolutionChanged", function (rs) {
        console.log("resolution  changed");
        console.log(rs);
    });
    player.on("FrameTypeChange", function (rs) {
        console.log("video encode mode changed");
        console.log(rs);
    });
    player.on("audioChange", function (rs) {
        console.log("audio encode changed");
        console.log(rs);
    });
    player.on("GetFrameRate", function (rs) {
        console.log("frame rate");
        console.log(rs);
    });

    player.init(canvasElement.value, videoElement.value);
    // window.__player = player;
}

function login() {
    const target = "10.168.1.100:80";
    setIP(target);
    RPC.login("admin", "zhzy@2021", false)
        .then((res) => {
            console.info("登录成功");
            isLogin = true;
            setCookie("DWebClientSessionID", "", -1);
            setCookie("DhWebClientSessionID", "", -1);
            /**
             * RPC.keepAlive 保活
             */
            _setSession(res.session);
            RPC.keepAlive(300, 60000, _getSession(), target, 0);
        })
        .catch((err) => {
            console.log(err);
        });
}

//回放
const onReplay = () => {
    onClosePlayback();
    if (!isLogin) {
        alert("请先登录再预览！");
        return;
    }
    let ip = "10.168.1.100";
    let port = 80;
    let username = "admin";
    let password = "zhzy@2021";
    let options = {
        wsURL: "ws://" + ip + ":" + port + "/rtspoverwebsocket",
        rtspURL: "rtsp://" + ip + ":" + port + "/" + replayRecord.FilePath,
        username: username,
        password: password,
        lessRateCanvas: true,
        playback: true,
        isPrivateProtocol: false,
        realm: RPC.realm, //设备登录返回的realm
        playbackIndex: 0,
        // h265AccelerationEnabled: true, // 硬解码是否开启，默认不开启
    };
    replayPlayer = new window.PlayerControl(options);
    isReplayPlayerShow.value = true;

    replayPlayer.on("WorkerReady", function () {
        console.log("replay workReady");
        replayPlayer.connect();
    });
    replayPlayer.on("DecodeStart", function (rs) {
        console.log("replay start decode");
        console.log(rs);
        decodeMode2.value = rs.decodeMode;
    });
    replayPlayer.on("PlayStart", function (rs) {
        console.log("replay play");
        console.log(rs);
    });
    replayPlayer.on("Error", function (rs) {
        console.log("replay error");
        console.log(rs);
    });
    replayPlayer.on("FileOver", function () {
        console.log("replay recorder play over");
        onClosePlayback();
    });
    replayPlayer.on("MSEResolutionChanged", function (rs) {
        console.log("replay resolution  changed");
        console.log(rs);
    });
    replayPlayer.on("FrameTypeChange", function (rs) {
        console.log("replay video encode mode changed");
        console.log(rs);
    });
    replayPlayer.on("audioChange", function (rs) {
        console.log("replay audio encode changed");
        console.log(rs);
    });
    replayPlayer.on("GetFrameRate", function (rs) {
        console.log("replay frame rate");
        console.log(rs);
    });
    replayPlayer.init(canvasElement2.value, videoElement2.value);
};

// //查询录像
const onSearchRecord = async (stringTime) => {
    console.log("stringTime", stringTime);

    let playChannel = 0;
    const getMediaFile = (params) => {
        return new Promise((resolve, reject) => {
            /**
             * RPC.MediaFileFind.instance 创建媒体文件查找实例
             * @returns {Promise}
             */
            RPC.MediaFileFind.instance()
                .then((json) => {
                    let queryId = json.result;
                    /**
                     * RPC.MediaFileFind.findFile 设置查找条件，并判断是否存在文件
                     * @param {number} queryId 实例id
                     * @param {object} params condition参数
                     * @returns {Promise}
                     */
                    RPC.MediaFileFind.findFile(queryId, params)
                        .then(() => {
                            findNextFile(queryId)
                                .then(() => {
                                    resolve(true);
                                })
                                .catch((err) => {
                                    reject(err);
                                });
                        })
                        .catch((err) => {
                            reject(err);
                        });
                })
                .catch((err) => {
                    reject(err);
                });
        });
    };
    const findNextFile = (queryId) => {
        return new Promise((resolve, reject) => {
            /**
             * RPC.MediaFileFind.findNextFile 在指定条件基础上查询文件信息
             * @param {number} queryId 实例
             * @param {object} 需要查找的数目
             * @returns {Promise}
             */
            RPC.MediaFileFind.findNextFile(queryId, { count: 1 })
                .then((data) => {
                    console.log("data", data);
                    if (data.found == 1) {
                        replayRecord = data.infos[0];
                        stopFind(queryId);
                        resolve(true);
                    } else {
                        reject(err);
                        stopFind(queryId);
                    }
                })
                .catch((err) => {
                    reject(err);
                    stopFind(queryId);
                });
        });
    };
    const stopFind = (object) => {
        return new Promise((resolve, reject) => {
            /**
             * PC.MediaFileFind.close 结束查询
             * @param {number} object 媒体文件查找实例ID
             * @returns {Promise}
             */
            RPC.MediaFileFind.close(object)
                .then(() => {
                    /**
                     * PC.MediaFileFind.destroy 销毁媒体文件查找实例
                     * @param {number} object 媒体文件查找实例ID
                     */
                    RPC.MediaFileFind.destroy(object);
                    resolve(true);
                })
                .catch(() => {
                    reject();
                })
                .finally(() => {});
        });
    };
    let tmpDir = [];
    try {
        /**
         * RPC.getDeviceAllInfo 获取存储信息
         * @param {string} 'getDeviceAllInfo' 方法名
         * @return {Promise}
         */
        tmpDir = await RPC.getDeviceAllInfo("getDeviceAllInfo");
    } catch (e) {
        console.log(e);
    }
    let dirs = null;
    if (tmpDir.info && tmpDir.info.length > 1) {
        dirs = "All";
    } else {
        //dirs = tmpDir.info?[0]?.Detail?[0]?.Path ?? '/mnt/sd';
        dirs =
            (tmpDir.info &&
                tmpDir.info[0] &&
                tmpDir.info[0].Detail &&
                tmpDir.info[0].Detail[0] &&
                tmpDir.info[0].Detail[0].Path) ||
            "/mnt/sd";
    }

    // let startTime = "2025-08-21 08:53:07";
    // let endTime = "2025-08-21 08:53:07";

    let params = {
        condition: {
            Channel: playChannel,
            Dirs: [dirs],
            StartTime: stringTime,
            EndTime: stringTime,
            Flags: null,
            Events: ["*"],
            Types: ["dav"],
        },
    };
    getMediaFile(params)
        .then(() => {
            onReplay();
        })
        .catch((err) => {
            if (err && err.error && err.error.code === 285409409) {
                alert("回放功能需要确保SD卡经过设备认证");
            } else {
                console.log("err", err);
                alert("无数据");
            }
        });
};

/**
 * @description 暂停回放
 */
const onPausePlayback = () => {
    replayPlayer?.pause();
};
/**
 * @description 继续回放
 */
const onContinuePlayback = () => {
    replayPlayer?.play();
};
/**
 * @description 停止回放
 */
const onClosePlayback = () => {
    if (replayPlayer) {
        replayPlayer.stop();
        replayPlayer.close();
        replayPlayer = null;
        isReplayPlayerShow.value = false;
    }
};
</script>

<style>
/* 动画关键帧 */
@keyframes dataFlow {
    0% {
        transform: translateY(100%) scale(0.2);
        opacity: 0;
    }
    20% {
        opacity: 1;
    }
    80% {
        opacity: 1;
    }
    100% {
        transform: translateY(-100%) scale(1);
        opacity: 0;
    }
}

@keyframes pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(22, 93, 255, 0.4);
    }
    70% {
        box-shadow: 0 0 0 15px rgba(22, 93, 255, 0);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(22, 93, 255, 0);
    }
}

@keyframes float {
    0%,
    100% {
        transform: translateY(0);
    }
    50% {
        transform: translateY(-10px);
    }
}

@keyframes rotate {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}

/* 全局图标样式 */
.header-icon {
    font-size: 24px;
    color: #1890ff;
    margin-right: 16px;
    vertical-align: middle;
}

.title-container {
    text-align: center;
    margin-bottom: 24px;
}

.main-title {
    font-size: 28px;
    font-weight: bold;
    color: rgb(240, 244, 255);
    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}

.content {
    padding: 24px;
}

.media-container {
    width: 100%;
    height: 100%;
}

.media-element {
    width: 100%;
    height: 720px;
    background-color: #000;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}

.video-card {
    background: rgba(10, 14, 23, 0.7);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}

.event-card {
    background: rgba(10, 14, 23, 0.7);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}

.event-item {
    margin-bottom: 16px;
    background: rgba(20, 25, 40, 0.6);
    border: 1px solid rgba(255, 255, 255, 0.05);
    transition: all 0.3s;
}

.event-item:hover {
    background: rgba(30, 35, 50, 0.8);
    transform: translateY(-2px);
}
.event-list {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

.img-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
}
.img-box {
    width: 186px;
    height: 108px;
}
.img-box img {
    width: 100%;
    height: 100%;
    object-fit: cover;  
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);

}
</style>
